<template>
    <div class="flow-container">
        <!-- 左侧可拖拽项目 -->
        <div class="sidebar">
            <div class="drag-box" v-for="item in draggableItems" :key="item.id">
                <div class="drag-title">{{ item.label }}</div>
                <div v-for="m in item.children" :key="m.id" class="draggable-item" :style="{backgroundColor:m.backgroundColor}" :class="`${m.dataType}-item`"
                    draggable="true" @dragstart="(event) => onDragStart(event, m)">
                    {{ m.label }}
                    </div>
            </div>
         
        </div>

        <!-- 右侧拖拽区域 -->
        <div class="flow-chart" @drop="onDrop" @dragover="onDragOver">
            <VueFlow fit-view-on-init elevate-edges-on-select :nodes="initNodes" :edges="initEdges">
                <DropzoneBackground
                    :style="{
                        backgroundColor: isDragOver ? '#e7f3ff' : 'transparent',
                        transition: 'background-color 0.2s ease',
                    }"
                >
                    <p v-if="isDragOver">Drop here</p>
                </DropzoneBackground>   
            </VueFlow>
        </div>

        <div class="footer">
          <el-button type="primary" @click="saveFlow">保存</el-button>
        </div>
    </div>
</template>

<script setup lang="ts">
import  DropzoneBackground from './DropzoneBackground.vue'
import { ref, onMounted } from 'vue'
import { Position, MarkerType } from '@vue-flow/core'

import {
    VueFlow,
    useVueFlow,
    Elements,
    FlowElement,
    Node,
    Edge,
} from '@vue-flow/core'
// 初始化 vue-flow
const { onConnect,fromObject, addEdges, addNodes, getNodes, nodes, edges,screenToFlowCoordinate,toObject } = useVueFlow()

const initNodes = ref([

])
const initEdges = ref([

])
const isDragOver = ref(false)
// 定义可拖拽的项目
const draggableItems = ref([
    {
        id: 'collection', label: '集合节点', children: [
            {id:1, label: '目标点',
            type:'default',
            dataType:'point_collection',
            targetPosition: Position.Top, // or Bottom, Left, Right,
            sourcePosition: Position.Bottom,
            backgroundColor: 'rgba(16, 185, 129, 1)',
            style: { backgroundColor: 'rgba(16, 185, 129, 0.5)', width: '200px', height: '100px' },
         },
            {id:2, label: '动作列表', type: 'default' ,
            dataType:'action_list_collection',
                targetPosition: Position.Top, // or Bottom, Left, Right,
            sourcePosition: Position.Bottom,
             backgroundColor: 'rgb(185 ,164 ,16)',
             style: { backgroundColor: 'rgba(185, 164, 16, 0.5)', width: '150px' },
            },
            {id:3, label: '动作集合', type: 'default',
            dataType:'action_collection',
                targetPosition: Position.Top, // or Bottom, Left, Right,
            sourcePosition: Position.Bottom,
              backgroundColor: 'rgb(63, 110 ,231)',
             style:{backgroundColor: 'rgba(63, 110 ,231,0.5)', width: '100px'}
             },
            {id:4, label: '动作指令', type: 'default' ,
            dataType:'action_order_collection',
                targetPosition: Position.Top, // or Bottom, Left, Right,
            sourcePosition: Position.Bottom,
               backgroundColor: 'rgb(76, 175 ,80)',
             style:{backgroundColor: 'rgba(76, 175, 80,0.5)', width: '80px'}
            },
        ]
    },
    {
        id: 'action', label: '动作', type: 'default', children: [
            {id:5, label: '无动作', type: 'default',dataType:'action',style:{ width: '80px'} },
            {id:6, label: '叉车动作', type: 'default',dataType:'action',style:{ width: '80px'} },
            {id:7, label: '复合动作', type: 'default',dataType:'action',style:{ width: '80px'} },
            {id:8, label: '顶升动作', type: 'default',dataType:'action',style:{ width: '80px'} },
            {id:9, label: '滚筒动作', type: 'default' ,dataType:'action',style:{ width: '80px'}},
            {id:10, label: '机械臂动作', type: 'default',dataType:'action',style:{ width: '80px'} },
            {id:11, label: '人工动作', type: 'default',dataType:'action',style:{ width: '80px'} },

        ]
    }
])

// 定义节点和边
const initialElements = ref<Elements>([
    // 初始节点
    { id: '1', type: 'input', label: '开始', position: { x: 250, y: 5 }, class: 'start-node',
          
    },
    { id: '2', label: '结束', position: { x: 250, y: 100 }, class: 'end-node',
 targetPosition: Position.Top, // or Bottom, Left, Right,
            sourcePosition: Position.Bottom
},

      {
    id: '2a',
    data: { label: 'child node' },
    position: { x: 10, y: 50 },
    parentNode: '1',
  },
])


// 处理连接事件
onConnect((params) => {
  console.log(params,"params.defineEmits.defineEmits.")
  
  // 获取源节点和目标节点
  const nodes = getNodes.value
  const sourceNode = nodes.find(node => node.id === params.source)
  const targetNode = nodes.find(node => node.id === params.target)
  
  // 检查节点是否存在
  if (!sourceNode || !targetNode) {
    console.log('无法找到源节点或目标节点')
    return
  }
  
  // 检查是否为同级节点（相同父节点或都是顶级节点）
  const isSameLevel = (sourceNode.parentNode || null) === (targetNode.parentNode || null)
  const isLevel = targetNode.dataType == sourceNode.dataType
  if (isSameLevel&&isLevel) {
    addEdges([{
      ...params,
      markerEnd: { type: MarkerType.ArrowClosed },
      style: { strokeWidth: 1 }
    }])
  } else {
    console.log('只能连接同级节点')
  }
})



// 处理拖拽开始事件
const onDragStart = (event: DragEvent, item: any) => {
    if (event.dataTransfer) {
        event.dataTransfer.setData('application/vueflow', JSON.stringify(item))
        event.dataTransfer.effectAllowed = 'move'
    }
}

// 处理拖拽放置事件
const onDrop = (event: DragEvent) => {
    event.preventDefault()
  
    if (event.dataTransfer) {
        const data = event.dataTransfer.getData('application/vueflow')
        
        if (data) {
            const item = JSON.parse(data)

            const positionEvent = { x: event.clientX, y: event.clientY }
            // 获取所有现有节点
            const nodes = getNodes.value
            // 定义节点类型的嵌套规则
            // key: 子节点类型, value: 允许作为父节点的类型数组
            let arr = {
              point_collection: [], // 目标点不能放在其他节点内
              action_list_collection: ['point_collection'], // 动作列表只能放在目标点内
              action_collection: ['action_list_collection'], // 动作集合只能放在动作列表内
              action_order_collection: ['action_collection'], // 动作指令只能放在动作集合内
              action: ['action_order_collection'] // 动作不能放在其他节点内
              
            }
            
            // 检查是否有节点在当前位置
            let parentNodeId = null
            let parentNode = null
            
            let tempNodes = nodes.filter((node) => {
              return arr[item.dataType].includes(node.dataType)
            })
            
            // 查找可能的父节点
            for (let i = tempNodes.length - 1; i >= 0; i--) {
                 const node = tempNodes[i]
                var domNode = document.querySelector(`.vue-flow [data-id="${node.id}"]`)
                
                if(domNode){
                  var rect = domNode.getBoundingClientRect()
                  if(positionEvent.x >= rect.left && positionEvent.x <= rect.right && 
                    positionEvent.y >= rect.top && positionEvent.y <= rect.bottom){
                    parentNodeId = node.id
                    parentNode = node
                    break // 找到父节点后退出循环
                  }
                }
            }
            const position = screenToFlowCoordinate({ x: event.clientX, y: event.clientY })
            
            // 添加新节点
            const newNode: any = {
                id: `${item.id}-${Date.now()}`,
                type: item.type,
                label: item.label,
                position,
                style:item.style?item.style:{},
                targetPosition: item.dataType != 'action'?Position.Top:'',
                sourcePosition: item.dataType != 'action'?Position.Bottom:'',
                class: `${item.dataType}-node`,
                draggable: true,
                dataType: item.dataType,
              
            }

            // 如果找到了父节点，设置parentNode属性
            if (parentNodeId && parentNode) {
                newNode.parentNode = parentNodeId
                newNode.extent = 'parent'
                newNode.expandParent = true
                
                // 调整位置为相对于父节点的坐标
                newNode.position = {
                    x: position.x - parentNode.position.x,
                    y: position.y - parentNode.position.y
                }
            }

            addNodes([newNode])
        }
    }
}

// 处理拖拽覆盖事件
const onDragOver = (event: DragEvent) => {
    event.preventDefault()
    if (event.dataTransfer) {
        event.dataTransfer.dropEffect = 'move'
    }
}
function saveFlow(){
  var obj = toObject()
  console.log(obj,"toObject")
}
</script>



<style scoped>
.drag-title{
  font-size: 20px;
  font-weight: bold;
}
.footer{
  position: absolute;
  right: 40px;
  bottom: 40px;
  z-index: 22;
  cursor: pointer;
}
.flow-container {
    display: flex;
    height: 100%;
    border: 1px solid #ccc;
    background-color: #f9f9f9;
}

.sidebar {
    width: 200px;
    padding: 20px;
    background-color: #eee;
    border-right: 1px solid #ccc;
}

.sidebar h3 {
    margin-top: 0;
}

.draggable-item {
    padding: 10px;
    margin-bottom: 10px;
    border-radius: 4px;
    cursor: move;
    text-align: center;
    font-weight: bold;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.collection-item {
    background-color: #4caf50;
    color: white;
}

.action-item {
    background-color: #2196f3;
    color: white;
}

.flow-chart {
    flex: 1;
    height: 100%;
}
.dnd-flow{
       flex: 1;
    height: 100%;
}
:deep(.vue-flow__node) {
    border-radius: 8px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
    padding: 10px;
    text-align: center;
    font-size: 12px;
}

:deep(.vue-flow__node-parent) {
    border: 2px dashed #4caf50;
    padding: 20px;
    background-color: rgba(16, 185, 129, 0.1);
}

:deep(.start-node) {
    background-color: #4caf50;
    color: white;
}

:deep(.end-node) {
    background-color: #f44336;
    color: white;
}

:deep(.collection-node) {
    background-color: #4caf50;
    color: white;
}

:deep(.action-node) {
    background-color: #2196f3;
    color: white;
    padding: 4px;
    border-radius: 4px;
}

:deep(.vue-flow__edge-path) {
    stroke: #333;
    stroke-width: 2px;
    stroke-dasharray: 5;
    animation: dash 1s linear infinite;
}

@keyframes dash {
    to {
        stroke-dashoffset: -20px;
    }
}

.flow-container :deep(.vue-flow__handle-bottom),.flow-container :deep(.vue-flow__handle-top){
    background-color: black;
    border-radius: 50%;
    border: 1px solid white;
    z-index: 99;
}
</style>